Repository navigation
Conversation
Co-authored-by: Julio Navarro <julionav@users.noreply.github.com>
Co-authored-by: Julio Navarro <julionav@users.noreply.github.com>
|
|
|
|
❌ Deploy Preview for stackblitz-docs failed. Why did it fail? →
|
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Heads up: Relaxing the old-key guard so we can merge this without syncing the Netlify env cleanup at the same time. Just ignoring the var isn't enough tho, Vite inlines every Follow-up plan: -> merge this, prod runs search on Side note: previews were also dying on Node 16 (site pin from 2021), fixed with the |
Summary of changes
Linear: BAC-1857. HackerOne: 3998832.
Problem
The docs site sends the Algolia API key to all visitors. This is necessary for DocSearch. But the key on developer.stackblitz.com is not a search-only key. Its ACL has write permissions:
addObject,deleteObject,deleteIndex,editSettings. Any visitor can use the key to change or delete thestackblitzindex.The repository does not contain the key. The build gets the key from the Netlify variable
VITE_ALGOLIA_KEY.Also, Vite puts every
VITE_*variable into the client bundle (theframeworkchunk), even when the code does not use that variable. Thus, if the old variable stays in Netlify, the old key continues to go to visitors.Solution
VITE_ALGOLIA_SEARCH_KEY.GET /1/keys/<key>. Algolia lets each key read its own ACL. If the ACL is not exactly["search"], the build fails. If the request fails (for example, HTTP 403 for a key that is not valid), the build fails.VITE_ALGOLIA_KEYis set, the build fails. This prevents the old key in the bundle.VITE_ALGOLIA_INDEX, sets the index name. The default isstackblitz.The guard is strict on purpose. Read-only extras such as
listIndexesandsettingsalso make the build fail.Implementation details
.vitepress/config.ts:getSearchConfigis nowasyncand the config usesawait. The new functionassertSearchOnlyKeydoes the ACL check.README.md: the variable list shows the new names. It also tells you not to put secrets inVITE_*variables.How to reproduce the problem (BEFORE)
Use only read-only requests. Do not write to the index.
curl -s https://developer.stackblitz.com/guides/user-guide/what-is-stackblitz, then get each/assets/*.jsfile in the page.VITE_ALGOLIA_KEYandapiKey. The result shows appYCVDUYWLVCand a key that starts with8fe79cd8.curl -s -H "X-Algolia-Application-Id: YCVDUYWLVC" -H "X-Algolia-API-Key: $KEY" https://YCVDUYWLVC-dsn.algolia.net/1/keys/$KEY.BEFORE: key in live page source (masked)
BEFORE: ACL of the live key
Build checks (AFTER)
We did not create a key on app
YCVDUYWLVC, because that is a write operation. The checks use public keys from other projects:ZTF29HGJ69, indexvitest). Its ACL is["search"].ML0LEBN7FQ). Its ACL is["search","listIndexes","settings"].Commands (keys are masked to 8 characters):
npx prettier --check .vitepress/config.ts README.mdpasses.AFTER: build guard checks and bundle scan
Search works with a search-only key. For this screenshot only, we changed
langtoen, because the Vitest index useslang: enand the site sendslang:en-US. We did not commit this change.AFTER: local search works with a search-only key
Ops steps (necessary — this PR alone does not stop the leak)
The old key is public now and must be deleted. Do these steps in this sequence:
YCVDUYWLVC), create a new API key. Give it only thesearchACL. Limit it to thestackblitzindex.VITE_ALGOLIA_SEARCH_KEYwith the new key.VITE_ALGOLIA_KEY. If you do not, the build fails (check C).8fe79cd8).GET /1/keys/<old key>must return HTTP 403.8fe79cd8. The ACL of the new key must be["search"].Also examine the Algolia index and settings for changes that you did not expect. The old key had write access for a long time (created 2021-12-07).
Note
We used only read-only Algolia requests:
GET /1/keysand search. We did not write to, delete, or change any index or setting.To show artifacts inline, enable in settings.